module secured.util;

import std.stdio;

import secured.openssl;

public enum uint FILE_BUFFER_SIZE = 32768;

@trusted public class CryptographicException : Exception
{
    this(string message)
    {
        super(message);
        debug {
        while(ERR_peek_error() != 0) {
            char[] buf = new char[512];
            ERR_error_string_n(ERR_get_error(), buf.ptr, 512);
            writeln(buf);
        }
        }
    }
}

@safe pure public bool constantTimeEquality(const ubyte[] a, const ubyte[] b)
{
    if(a.length != b.length)
        return false;

    int result = 0;
    for(int i = 0; i < a.length; i++)
        result |= a[i] ^ b[i];
    return result == 0;
}

unittest
{
    import std.digest;
    import std.stdio;
    import secured.random;

    writeln("Testing Constant Time Equality:");

    //Test random data
    ubyte[] rnd1 = random(32);
    ubyte[] rnd2 = random(32);
    writeln("Testing with Random Data");
    assert(!constantTimeEquality(rnd1, rnd2));

    //Test equal data
    ubyte[48] key1 = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
                       0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
                       0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ];
    ubyte[48] key2 = [ 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
                       0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
                       0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF ];
    writeln("Testing with Equal Data");
    assert(constantTimeEquality(key1, key2));
}
